snow-flow 10.0.21 → 10.0.22

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.21",
3
+ "version": "10.0.22",
4
4
  "name": "snow-flow",
5
5
  "description": "Snow-Flow - ServiceNow Multi-Agent Development Framework powered by AI",
6
6
  "license": "Elastic-2.0",
@@ -1284,6 +1284,7 @@ function DialogAuthEnterpriseCombined() {
1284
1284
  | "code"
1285
1285
  | "verifying-enterprise"
1286
1286
  | "checking-portal-sn"
1287
+ | "select-sn-instance"
1287
1288
  | "sn-method"
1288
1289
  | "sn-instance"
1289
1290
  | "sn-oauth-clientid"
@@ -1309,6 +1310,18 @@ function DialogAuthEnterpriseCombined() {
1309
1310
  clientSecret?: string
1310
1311
  } | null>(null)
1311
1312
 
1313
+ // ServiceNow instances from enterprise portal (for multi-instance selection)
1314
+ const [snInstances, setSnInstances] = createSignal<
1315
+ Array<{
1316
+ id: number
1317
+ instanceName: string
1318
+ instanceUrl: string
1319
+ environmentType: string
1320
+ isDefault: boolean
1321
+ enabled: boolean
1322
+ }>
1323
+ >([])
1324
+
1312
1325
  // ServiceNow state
1313
1326
  const [snMethod, setSnMethod] = createSignal<"oauth" | "basic">("oauth")
1314
1327
  const [snInstance, setSnInstance] = createSignal("")
@@ -1369,6 +1382,9 @@ function DialogAuthEnterpriseCombined() {
1369
1382
  setSessionId("")
1370
1383
  setAuthCode("")
1371
1384
  setTimeout(() => subdomainInput?.focus(), 10)
1385
+ } else if (currentStep === "select-sn-instance") {
1386
+ // Can't re-do enterprise auth, go back to main auth menu
1387
+ dialog.replace(() => <DialogAuth />)
1372
1388
  } else if (currentStep === "sn-method") {
1373
1389
  // Can't go back to enterprise flow, go to main menu
1374
1390
  dialog.replace(() => <DialogAuth />)
@@ -1520,28 +1536,42 @@ function DialogAuthEnterpriseCombined() {
1520
1536
  duration: 3000,
1521
1537
  })
1522
1538
 
1523
- // Check if enterprise portal has ServiceNow credentials
1539
+ // Check if enterprise portal has ServiceNow instances
1524
1540
  setStep("checking-portal-sn")
1525
- const portalCreds = await fetchPortalSnCredentials(portalUrl, data.token)
1541
+ const instances = await fetchPortalSnInstances(portalUrl, data.token)
1526
1542
 
1527
- if (portalCreds) {
1528
- // Portal has ServiceNow credentials - use them directly
1529
- setPortalSnCredentials(portalCreds)
1543
+ if (instances.length === 0) {
1544
+ // No instances manual setup
1545
+ toast.show({
1546
+ variant: "info",
1547
+ message: "No ServiceNow instances found on portal. Please configure manually.",
1548
+ duration: 3000,
1549
+ })
1550
+ setStep("sn-method")
1551
+ } else if (instances.length === 1) {
1552
+ // Single instance — fetch creds and proceed
1530
1553
  toast.show({
1531
1554
  variant: "info",
1532
- message: "ServiceNow credentials found in enterprise portal!",
1555
+ message: `ServiceNow instance found: ${instances[0].instanceName}`,
1533
1556
  duration: 3000,
1534
1557
  })
1535
- // Skip manual ServiceNow input, go directly to completing
1536
- await startBothMcpServersWithPortalCreds(portalUrl, data.token, portalCreds, data.user)
1558
+ const creds = await fetchPortalSnInstanceById(portalUrl, data.token, instances[0].id)
1559
+ if (creds) {
1560
+ setPortalSnCredentials(creds)
1561
+ await startBothMcpServersWithPortalCreds(portalUrl, data.token, creds, data.user)
1562
+ } else {
1563
+ toast.show({ variant: "error", message: "Failed to fetch instance credentials.", duration: 3000 })
1564
+ setStep("sn-method")
1565
+ }
1537
1566
  } else {
1538
- // No ServiceNow credentials on portal - ask user to input manually
1567
+ // Multiple instances show selection
1568
+ setSnInstances(instances)
1539
1569
  toast.show({
1540
1570
  variant: "info",
1541
- message: "No ServiceNow credentials found on portal. Please configure manually.",
1571
+ message: `${instances.length} ServiceNow instances found. Please select one.`,
1542
1572
  duration: 3000,
1543
1573
  })
1544
- setStep("sn-method")
1574
+ setStep("select-sn-instance")
1545
1575
  }
1546
1576
  } catch (e) {
1547
1577
  toast.show({ variant: "error", message: e instanceof Error ? e.message : "Verification failed" })
@@ -1552,38 +1582,58 @@ function DialogAuthEnterpriseCombined() {
1552
1582
 
1553
1583
  // === Portal ServiceNow Credentials ===
1554
1584
 
1555
- const fetchPortalSnCredentials = async (
1585
+ const fetchPortalSnInstances = async (
1556
1586
  portalUrl: string,
1557
- token: string
1558
- ): Promise<{ instanceUrl: string; clientId: string; clientSecret: string } | null> => {
1587
+ token: string,
1588
+ ): Promise<
1589
+ Array<{
1590
+ id: number
1591
+ instanceName: string
1592
+ instanceUrl: string
1593
+ environmentType: string
1594
+ isDefault: boolean
1595
+ enabled: boolean
1596
+ }>
1597
+ > => {
1559
1598
  try {
1560
- const response = await fetch(`${portalUrl}/api/user-credentials/servicenow/default`, {
1599
+ const response = await fetch(`${portalUrl}/api/user-credentials/servicenow/instances`, {
1561
1600
  method: "GET",
1562
1601
  headers: {
1563
1602
  Authorization: `Bearer ${token}`,
1564
1603
  Accept: "application/json",
1565
1604
  },
1566
1605
  })
1567
-
1568
- if (!response.ok) {
1569
- return null
1570
- }
1571
-
1606
+ if (!response.ok) return []
1572
1607
  const data = await response.json()
1608
+ if (!data.success || !Array.isArray(data.instances)) return []
1609
+ return data.instances.filter((i: any) => i.enabled)
1610
+ } catch {
1611
+ return []
1612
+ }
1613
+ }
1573
1614
 
1574
- if (!data.success || !data.instance) {
1575
- return null
1576
- }
1577
-
1578
- const instance = data.instance
1579
- if (!instance.instanceUrl || !instance.clientId || !instance.clientSecret) {
1580
- return null
1581
- }
1582
-
1615
+ const fetchPortalSnInstanceById = async (
1616
+ portalUrl: string,
1617
+ token: string,
1618
+ instanceId: number,
1619
+ ): Promise<{ instanceUrl: string; clientId: string; clientSecret: string } | null> => {
1620
+ try {
1621
+ const response = await fetch(`${portalUrl}/api/user-credentials/servicenow/instances/${instanceId}`, {
1622
+ method: "GET",
1623
+ headers: {
1624
+ Authorization: `Bearer ${token}`,
1625
+ Accept: "application/json",
1626
+ },
1627
+ })
1628
+ if (!response.ok) return null
1629
+ const data = await response.json()
1630
+ if (!data.success || !data.instance) return null
1631
+ const inst = data.instance
1632
+ if (!inst.instanceUrl || !inst.clientId || !inst.clientSecret) return null
1583
1633
  return {
1584
- instanceUrl: instance.instanceUrl,
1585
- clientId: instance.clientId,
1586
- clientSecret: instance.clientSecret,
1634
+ instanceUrl: inst.instanceUrl,
1635
+ clientId: inst.clientId,
1636
+ clientSecret: inst.clientSecret,
1587
1637
  }
1588
1638
  } catch {
1589
1639
  return null
@@ -1938,6 +1988,33 @@ function DialogAuthEnterpriseCombined() {
1938
1988
  </box>
1939
1989
  </Show>
1940
1990
 
1991
+ {/* Step 4c: Select ServiceNow instance */}
1992
+ <Show when={step() === "select-sn-instance"}>
1993
+ <DialogSelect
1994
+ title="Select ServiceNow Instance"
1995
+ options={snInstances().map((inst) => ({
1996
+ title: inst.instanceName,
1997
+ value: String(inst.id),
1998
+ description: inst.instanceUrl,
1999
+ footer: inst.environmentType + (inst.isDefault ? " (default)" : ""),
2000
+ category: "ServiceNow Instances",
2001
+ onSelect: async () => {
2002
+ setStep("completing")
2003
+ const portalUrl = `https://${subdomain().trim().toLowerCase()}.snow-flow.dev`
2004
+ const token = enterpriseData().token!
2005
+ const creds = await fetchPortalSnInstanceById(portalUrl, token, inst.id)
2006
+ if (creds) {
2007
+ setPortalSnCredentials(creds)
2008
+ await startBothMcpServersWithPortalCreds(portalUrl, token, creds, enterpriseData().user)
2009
+ } else {
2010
+ toast.show({ variant: "error", message: "Failed to fetch instance credentials.", duration: 3000 })
2011
+ setStep("sn-method")
2012
+ }
2013
+ },
2014
+ }))}
2015
+ />
2016
+ </Show>
2017
+
1941
2018
  {/* Step 5: Choose ServiceNow method */}
1942
2019
  <Show when={step() === "sn-method"}>
1943
2020
  <box gap={1}>