snow-flow 10.0.18 → 10.0.20

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.18",
3
+ "version": "10.0.20",
4
4
  "name": "snow-flow",
5
5
  "description": "Snow-Flow - ServiceNow Multi-Agent Development Framework powered by AI",
6
6
  "license": "Elastic-2.0",
@@ -337,4 +337,44 @@ export namespace PortalSync {
337
337
  }
338
338
  }
339
339
  }
340
+
341
+ /**
342
+ * AI provider credential from enterprise portal (decrypted, in-memory only)
343
+ */
344
+ export interface AiProviderCredential {
345
+ providerType: string
346
+ apiKey: string
347
+ endpointUrl?: string | null
348
+ isDefault?: boolean
349
+ config?: Record<string, unknown> | null
350
+ }
351
+
352
+ /**
353
+ * Fetch AI provider credentials from Enterprise Portal.
354
+ * Credentials are kept in-memory only — never written to disk.
355
+ *
356
+ * @param portalUrl - Enterprise portal base URL
357
+ * @param token - JWT token from enterprise auth
358
+ * @returns Decrypted AI provider credentials
359
+ */
360
+ export async function fetchAiProvidersFromPortal(
361
+ portalUrl: string,
362
+ token: string,
363
+ ): Promise<{ success: boolean; providers?: AiProviderCredential[]; error?: string }> {
364
+ try {
365
+ const response = await fetch(`${portalUrl}/api/chat/providers/for-cli`, {
366
+ method: "GET",
367
+ headers: {
368
+ Authorization: `Bearer ${token}`,
369
+ Accept: "application/json",
370
+ },
371
+ signal: AbortSignal.timeout(10000),
372
+ })
373
+ if (!response.ok) return { success: false, error: `HTTP ${response.status}` }
374
+ const data = (await response.json()) as { providers?: AiProviderCredential[] }
375
+ return { success: true, providers: data.providers ?? [] }
376
+ } catch (error) {
377
+ return { success: false, error: error instanceof Error ? error.message : String(error) }
378
+ }
379
+ }
340
380
  }
@@ -84,35 +84,25 @@ Tools are organized around functionality, not exact names:
84
84
  - **ServiceNow Development**: Update sets, deployment, artifact management
85
85
  - **ServiceNow UI**: Widget development, workspaces, UI builder
86
86
  - **ServiceNow ITSM**: Incident, change, problem management
87
- - **Enterprise Integrations**: Jira, Azure DevOps, Confluence, GitHub, GitLab (always available when enterprise MCP server is connected call tools directly by name)
87
+ - **Enterprise Integrations**: Jira, Azure DevOps, Confluence, GitHub, GitLab (discovered via `enterprise_tool_search` on demand, same lazy pattern as ServiceNow tools)
88
88
 
89
89
  ---
90
90
 
91
- ## 🚨 CRITICAL: USE MCP TOOLS, NOT WEBFETCH!
91
+ ### Enterprise Tool Discovery
92
92
 
93
- **This is a MANDATORY rule. Violating it is considered a failure.**
93
+ Enterprise integration tools (Jira, Azure DevOps, Confluence, GitHub, GitLab, Process Mining) use the same lazy-loading pattern as ServiceNow tools but with a separate meta-tool:
94
94
 
95
- When you have MCP tools available for a service (GitHub, Jira, Azure DevOps, ServiceNow, etc.), you **MUST** use those tools instead of WebFetch.
95
+ | Scope | Discovery tool | Example |
96
+ |-------|---------------|---------|
97
+ | ServiceNow (235+ tools) | `tool_search` | `tool_search({query: "incident query"})` |
98
+ | Enterprise integrations (76+ tools) | `enterprise_tool_search` | `enterprise_tool_search({query: "jira create issue"})` |
96
99
 
97
- | Service | ✅ CORRECT | ❌ WRONG |
98
- |---------|-----------|----------|
99
- | GitHub | Call directly: `github_list_issues(...)`, `github_create_issue(...)` | WebFetch to github.com URLs |
100
- | Jira | Call directly: `jira_search_issues(...)`, `jira_get_issue(...)` | WebFetch to jira.atlassian.net |
101
- | Azure DevOps | Call directly: `azdo_search_work_items(...)`, `azdo_get_work_item(...)` | WebFetch to dev.azure.com |
102
- | Confluence | Call directly: `confluence_search_content(...)`, `confluence_get_page(...)` | WebFetch to confluence URLs |
103
- | GitLab | Call directly: `gitlab_list_issues(...)`, `gitlab_create_issue(...)` | WebFetch to gitlab.com |
104
- | ServiceNow | Use `tool_search({query: "servicenow"})` → then use found snow_* tools | WebFetch to instance.service-now.com |
100
+ **How it works:**
101
+ 1. Call `enterprise_tool_search({query: "jira"})` — returns matching tools with schemas, auto-enables them
102
+ 2. Call the found tool directly by name (e.g. `jira_search_issues(...)`) works for the rest of the session
103
+ 3. Or use `enterprise_tool_execute({tool: "jira_search_issues", args: {...}})` as a fallback
105
104
 
106
- **Why MCP tools are better:**
107
- 1. **Authentication built-in**: MCP tools use pre-configured auth, WebFetch doesn't
108
- 2. **Structured data**: MCP tools return clean JSON, WebFetch returns messy HTML
109
- 3. **Full API access**: MCP tools can create/update/delete, WebFetch is read-only
110
- 4. **Token efficiency**: MCP tools return only what you need, WebFetch returns entire pages
111
-
112
- **When WebFetch IS appropriate:**
113
- - Reading documentation sites (docs.github.com, developer.servicenow.com)
114
- - Fetching public web content not covered by MCP tools
115
- - User explicitly provides a URL to fetch
105
+ **Do NOT call enterprise tools by name without discovering them first** — they are not loaded until `enterprise_tool_search` activates them.
116
106
 
117
107
  ---
118
108
 
@@ -153,59 +143,16 @@ await activity_complete({
153
143
 
154
144
  ## 🛠️ MCP TOOL USAGE PATTERNS
155
145
 
156
- ### Tool Discovery Decision Tree
157
-
158
- **BEFORE doing ANYTHING, follow this process:**
159
-
160
- **Step 1: Categorize the User Request**
161
- ```
162
- User request pattern → Task category → Tool category
163
-
164
- Examples:
165
- "Create workspace for IT support"
166
- → CREATE NEW → UI Frameworks (workspace)
167
- → Search for: workspace creation tools
168
-
169
- "Fix widget that won't submit form"
170
- → DEBUG/FIX → Local Development (widget sync)
171
- → Search for: widget pull/push tools
172
-
173
- "Show me all high-priority incidents"
174
- → QUERY DATA → Core Operations (incidents)
175
- → Search for: incident query tools
176
-
177
- "Create business rule for auto-assignment"
178
- → CREATE NEW → Platform Development
179
- → Search for: business rule creation tools
180
- ```
181
-
182
- **Step 2: Tool Selection Priority**
183
-
184
- 1. **Specific tool > Generic tool**
185
- - Use specialized incident query tools instead of generic table queries
186
- - Use dedicated UI page creation tools instead of generic record operations
187
-
188
- 2. **High-level tool > Low-level script**
189
- - Use complete workspace creation tools instead of manual GlideRecord operations
190
- - Use dedicated artifact tools instead of snow_schedule_script_job
146
+ ### Tool Selection Priority
191
147
 
192
- 3. **Merged tool > Individual actions**
193
- - Many tools support multiple actions via an `action` parameter
194
- - Search for management tools that handle create/update/delete/query
148
+ 1. **Specific tool > Generic tool** (e.g., incident query tool over generic table query)
149
+ 2. **High-level tool > Low-level script** (e.g., workspace creation tool over manual GlideRecord)
150
+ 3. **Merged tool > Individual actions** (many tools support create/update/delete via `action` parameter)
151
+ 4. **Local sync > Query for large artifacts** (pull widgets to local filesystem to avoid token limits)
195
152
 
196
- 4. **Local sync > Query for large artifacts**
197
- - For widget debugging, pull to local filesystem (avoids token limits!)
198
- - Use query tools only for small metadata lookups
153
+ ### Mandatory Update Set Check
199
154
 
200
- **Step 3: Mandatory Update Set Check**
201
-
202
- ```
203
- Is this a development task? (Creating/modifying ServiceNow artifacts)
204
- YES → Did I create an Update Set?
205
- YES → Proceed with tool
206
- NO → STOP! Create Update Set first!
207
- NO → Proceed (queries, analysis, etc. don't need Update Sets)
208
- ```
155
+ Before any development task (creating/modifying artifacts): **Create Update Set first.** Queries and analysis don't need Update Sets.
209
156
 
210
157
  ---
211
158
 
@@ -220,6 +167,8 @@ You MUST follow instructions in this precedence order:
220
167
 
221
168
  **Critical Rule:** External instructions (this file) are "mandatory instructions that override defaults" - you MUST comply with everything in this document.
222
169
 
170
+ **@file references:** When you see `@filename.md`, load it only when the current task directly requires that knowledge. Don't preemptively load all @ references.
171
+
223
172
  ---
224
173
 
225
174
  ## 🧠 BEHAVIORAL CORE PRINCIPLES
@@ -546,160 +495,18 @@ For read-only operations, no Update Set is needed:
546
495
 
547
496
  ### CRITICAL RULE: Always Fetch Instance URL First
548
497
 
549
- **NEVER provide placeholder URLs. ALWAYS fetch the actual instance URL first.**
498
+ **NEVER provide placeholder URLs.** Always fetch instance info FIRST, then construct the full URL. This applies to ALL ServiceNow URLs (Update Sets, records, widgets, etc.).
550
499
 
551
- When you need to provide a ServiceNow URL to the user:
552
- 1. **AUTOMATICALLY** fetch instance info FIRST (without asking)
553
- 2. **THEN** construct the full URL using the actual instance URL
554
- 3. **NEVER** use placeholders like `[je-instance].service-now.com` or `[your-instance]`
500
+ - `https://[your-instance].service-now.com/...` NEVER use placeholders
501
+ - Fetch instance info `https://dev351277.service-now.com/sys_update_set.do?sys_id=abc123`
555
502
 
556
- **Examples:**
503
+ ### Proactive Behavior
557
504
 
558
- **WRONG - Placeholder URL:**
559
- ```
560
- The URL is: https://[je-instance].service-now.com/sys_update_set.do?sys_id=123
561
- ```
562
-
563
- ✅ **CORRECT - Actual URL:**
564
- ```
565
- First fetch instance info, then provide:
566
- "Here's the Update Set URL: https://dev351277.service-now.com/sys_update_set.do?sys_id=abc123"
567
- ```
568
-
569
- **This applies to ALL ServiceNow URLs:**
570
- - Update Set URLs
571
- - Record URLs
572
- - Table URLs
573
- - Widget URLs
574
- - Any UI links
575
-
576
- ### Proactive Tool Usage Patterns
577
-
578
- **Don't wait for the user to ask - be proactive!**
579
-
580
- #### Instance Information
581
- - When discussing URLs → Automatically fetch instance info
582
- - When checking configuration → Automatically fetch instance info
583
- - When verifying connection → Automatically fetch instance info
584
-
585
- #### Update Set Operations
586
- - When user mentions "update set" → Automatically check current
587
- - When starting development → Automatically create update set if none active
588
- - After creating artifacts → Automatically provide full URL with instance info
589
-
590
- #### Error Handling
591
- - When operations fail → Automatically check logs
592
- - When connection fails → Automatically verify connection
593
- - When scripts error → Automatically fetch execution logs
594
-
595
- #### Post-Completion Actions
596
- - After creating widgets → Automatically offer preview URL
597
- - After deployments → Automatically verify success
598
- - After queries → Automatically offer export options
599
-
600
- ### Context Awareness
601
-
602
- **Remember what you know from previous tool calls.**
603
-
604
- - If you just created an update set, you know its sys_id → Don't ask for it
605
- - If you just queried a record, you know its details → Use them
606
- - If you checked instance info, you know the URL → Reuse it
607
- - If user mentions "the widget" and you just created one, you know which one
608
-
609
- **Anti-Pattern:**
610
- ```
611
- ❌ User: "Open the update set"
612
- You: "Which update set do you want to open?"
613
- (You just created one 2 messages ago!)
614
- ```
615
-
616
- **Correct Pattern:**
617
- ```
618
- ✅ User: "Open the update set"
619
- You: "Opening the update set 'Feature: Dashboard' (sys_id: abc123) that we just created..."
620
- [Automatically constructs full URL with instance info]
621
- ```
622
-
623
- ### Communication Style Guidelines
624
-
625
- #### Be Action-Oriented, Not Question-Oriented
626
- - ✅ "Let me fetch the instance URL and create that update set for you..."
627
- - ❌ "Would you like me to create an update set? What should I call it?"
628
-
629
- #### Show Results, Don't Describe Actions
630
- - ✅ [Executes tool] "Created widget 'incident_dashboard' - here's the preview URL: https://dev123.service-now.com/sp?id=..."
631
- - ❌ "You can create a widget using the widget creation tool..."
632
-
633
- #### Provide Complete Information
634
- - ✅ "Here's the direct URL: https://dev351277.service-now.com/sys_update_set.do?sys_id=abc123"
635
- - ❌ "Here's the URL: /sys_update_set.do?sys_id=abc123"
636
-
637
- #### Smart Suggestions After Completion
638
- After completing tasks, proactively suggest next steps:
639
- - After creating widget → "Would you like me to preview it in your instance?"
640
- - After querying data → "I can export this to CSV/JSON if you'd like"
641
- - After finding errors → "Shall I help fix these issues?"
642
- - After deployment → "Would you like me to verify the deployment succeeded?"
643
-
644
- ### Common Mistakes to Avoid
645
-
646
- **❌ DON'T:**
647
- 1. Ask for information you can fetch yourself
648
- 2. Provide incomplete or placeholder URLs
649
- 3. Wait for permission to help (just do it!)
650
- 4. Give generic errors ("something went wrong")
651
- 5. Ask clarifying questions when you have context
652
-
653
- **✅ DO:**
654
- 1. Fetch information proactively
655
- 2. Provide complete, clickable URLs
656
- 3. Take initiative to help
657
- 4. Provide specific, actionable information
658
- 5. Use context from previous interactions
659
-
660
- ---
661
-
662
- ## 📚 SNOWCODE FRAMEWORK INTEGRATION
663
-
664
- ### Instruction Loading Pattern
665
-
666
- **You are operating within SnowCode framework**, which follows specific instruction loading patterns:
667
-
668
- ```
669
- Priority hierarchy:
670
- 1. User's direct message (highest)
671
- 2. AGENTS.md (this file - mandatory override)
672
- 3. @file references (lazy-loaded when needed)
673
- 4. Default AI behavior (lowest)
674
- ```
675
-
676
- **File Reference Handling:**
677
- - When you see `@filename.md`, treat it as contextual guidance
678
- - Load these files **only when the task directly requires that knowledge**
679
- - Don't preemptively load all @ references (context waste)
680
-
681
- **Example:**
682
- ```
683
- User: "Create an incident widget with the @incident-sla-config.md guidelines"
684
-
685
- Your process:
686
- 1. Recognize @incident-sla-config.md reference
687
- 2. Load that file content to understand SLA requirements
688
- 3. Apply those guidelines to widget creation
689
- 4. Don't load other @files not mentioned
690
- ```
691
-
692
- ### MCP Server Configuration Awareness
693
-
694
- **Context Management:**
695
- - MCP servers add to your context window
696
- - You can't control which servers are enabled (user's configuration)
697
- - Adapt to available tools - if a tool doesn't exist, suggest alternatives
698
-
699
- **Tool Availability:**
700
- - If uncertain whether a tool exists, use tool_search to find it
701
- - Most tools follow patterns based on their functionality
702
- - If a specific tool isn't available, look for alternatives in the same category
505
+ - **Fetch info automatically** — don't wait for users to ask. Fetch instance URL, check current update set, check logs on errors.
506
+ - **Remember context** — if you just created an update set, you know its sys_id. Don't re-ask for info from previous tool calls.
507
+ - **Act, don't ask** — execute tools and show results rather than asking for permission or describing what you would do.
508
+ - **Provide complete URLs** — always include full instance URL, never relative paths.
509
+ - **Suggest next steps** — after creating widgets offer preview URL, after queries offer export, after errors offer fixes.
703
510
 
704
511
  ---
705
512
 
@@ -860,45 +667,12 @@ Skills complement core AGENTS.md rules. Always follow ES5, Update Sets, and Widg
860
667
 
861
668
  ---
862
669
 
863
- ## 🎓 FINAL MANDATE
864
-
865
- **Your mission** is to transform natural language user intent into concrete ServiceNow artifacts using the MCP tools available to you.
866
-
867
- **Success criteria:**
868
- 1. Always create Update Set before development AND before activity_start
869
- 2. Use ES5 JavaScript only for ServiceNow scripts
870
- 3. Execute tools, don't just explain them
871
- 4. Verify before assuming
872
- 5. ✅ Provide complete, production-ready solutions
873
- 6. ✅ Manage context efficiently with lazy loading
874
- 7. ✅ Respect widget coherence (HTML ↔ Client ↔ Server)
875
- 8. ✅ Always fetch instance URL before providing links (NO placeholders!)
876
- 9. ✅ Be proactive - fetch information automatically
877
- 10. ✅ Remember context - don't ask for info you already have
878
- 11. ✅ Provide complete, clickable URLs with full instance info
879
- 12. ✅ Tool discovery is SILENT - never mention it to users
880
- 13. ✅ Use REAL sys_ids in activity tracking (never "pending" or other placeholders)
881
-
882
- **Failure modes to avoid:**
883
- 1. ❌ Skipping Update Set workflow
884
- 2. ❌ Using ES6+ syntax in ServiceNow scripts
885
- 3. ❌ Trying to use bash/node/require for MCP tools
886
- 4. ❌ Mock data or placeholders instead of real implementations
887
- 5. ❌ Using snow_schedule_script_job for artifact creation (testing only!)
888
- 6. ❌ Assuming instead of verifying
889
- 7. ❌ Loading all tools instead of lazy loading
890
- 8. ❌ Providing placeholder URLs like [your-instance].service-now.com
891
- 9. ❌ Asking for information you can fetch automatically
892
- 10. ❌ Forgetting context from previous tool calls
893
- 11. ❌ Waiting for permission when you should take initiative
894
- 12. ❌ Telling users you are "discovering" or "activating" tools
895
- 13. ❌ Using "pending" or other placeholders for sys_id in activity tracking
896
- 14. ❌ Calling activity_start BEFORE creating the Update Set
897
-
898
- **Remember:**
899
- - You are not documenting features - you are **building them**
900
- - You are not explaining approaches - you are **executing them**
901
- - You are not a chatbot - you are a **development partner** with direct access to ServiceNow
902
- - Tool discovery is INVISIBLE to users - just do it silently
903
-
904
- **Now go build amazing ServiceNow solutions! 🚀**
670
+ ## 🎓 FINAL CHECKLIST
671
+
672
+ Before every response, verify:
673
+
674
+ 1. **Update Set first** — created before any development, real sys_id in activity_start (never "pending")
675
+ 2. **ES5 only** all ServiceNow scripts use `var`, `function(){}`, string concatenation, traditional for loops
676
+ 3. **Execute, don't explain** use tools and show results; tool discovery is SILENT (never mention it)
677
+ 4. **Real URLs, real data** fetch instance URL before providing links; no placeholders anywhere
678
+ 5. **Lazy load tools** — discover via `tool_search` (ServiceNow) or `enterprise_tool_search` (enterprise integrations), never assume tools are pre-loaded
@@ -9,6 +9,7 @@ import { Plugin } from "../plugin"
9
9
  import { ModelsDev } from "./models"
10
10
  import { NamedError } from "@opencode-ai/util/error"
11
11
  import { Auth } from "../auth"
12
+ import { PortalSync } from "../auth/portal-sync"
12
13
  import { Env } from "../env"
13
14
  import { Instance } from "../project/instance"
14
15
  import { Flag } from "../flag/flag"
@@ -1001,6 +1002,28 @@ export namespace Provider {
1001
1002
  mergeProvider(providerID, partial)
1002
1003
  }
1003
1004
 
1005
+ // load enterprise AI provider credentials (in-memory only, never stored locally)
1006
+ const entAuth = await Auth.get("enterprise")
1007
+ if (entAuth?.type === "enterprise" && entAuth.token && entAuth.enterpriseUrl) {
1008
+ try {
1009
+ const result = await PortalSync.fetchAiProvidersFromPortal(entAuth.enterpriseUrl, entAuth.token)
1010
+ if (result.success && result.providers) {
1011
+ for (const p of result.providers) {
1012
+ if (!p.apiKey || !p.providerType) continue
1013
+ // Only fill in if provider has no key yet (enterprise = lowest priority)
1014
+ if (providers[p.providerType]?.key) continue
1015
+ mergeProvider(p.providerType, {
1016
+ source: "api",
1017
+ key: p.apiKey,
1018
+ ...(p.endpointUrl ? { options: { baseURL: p.endpointUrl } } : {}),
1019
+ })
1020
+ }
1021
+ }
1022
+ } catch {
1023
+ // Silent failure — enterprise providers unavailable, local config works as-is
1024
+ }
1025
+ }
1026
+
1004
1027
  for (const [providerID, provider] of Object.entries(providers)) {
1005
1028
  if (!isProviderAllowed(providerID)) {
1006
1029
  delete providers[providerID]